home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / et / et3_0-a1.lha / et3 / src / FileDialog.C < prev    next >
C/C++ Source or Header  |  1992-08-24  |  8KB  |  384 lines

  1. #ifdef __GNUG__
  2. #pragma implementation
  3. #endif
  4.  
  5. #include "FileDialog.h"
  6.  
  7. #include "Class.h"
  8. #include "PopupItem.h"
  9. #include "ImageItem.h"
  10. #include "BorderItems.h"
  11. #include "Buttons.h"
  12. #include "ScrollBar.h"
  13. #include "CollView.h"
  14. #include "OrdColl.h"
  15. #include "Data.h"
  16. #include "Fields.h"
  17. #include "Form.h"
  18. #include "Menu.h"
  19. #include "Alert_e.h"
  20. #include "Scroller.h"
  21. #include "Document.h"
  22. #include "Application.h"
  23. #include "Error.h"
  24. #include "String.h"
  25.  
  26. const Point cIconSize(16);
  27.  
  28. //---- FileDialog --------------------------------------------------------------
  29.  
  30. NewMetaImpl(FileDialog, Dialog, (TP(eti), TP(title), TP(initDir), TE(flags),
  31.     TP(collview), TP(doc), TP(pathPopup)));
  32.  
  33. FileDialog::FileDialog(char *ti) : Dialog(ti)
  34. {
  35.     title= new TextItem(ti);
  36.     doc= 0;
  37.     fileData= 0;
  38.     initDir= 0;
  39.     pathList= 0;
  40.     current= 0;
  41. }
  42.  
  43. FileDialog::~FileDialog()
  44. {
  45.     SafeDelete(fileData);
  46.     SafeDelete(initDir);
  47.     SafeDelete(collview);
  48.     if (pathList) {
  49.     pathList->FreeAll();
  50.     SafeDelete(pathList);
  51.     }
  52.     SafeDelete(current);
  53. }
  54.  
  55. char *FileDialog::FileName()
  56. {
  57.     return fileData->FullName();
  58. }
  59.  
  60. int FileDialog::ShowInWindow(FileDialogFlags f, Clipper *fp, EvtHandler *eh, char *p)
  61. {
  62.     flags= f;
  63.     doc= eh;
  64.  
  65.     if (p == 0) {
  66.     if (f == eFDRead)
  67.         p= "Open File Named:";
  68.     else if (f == eFDWrite)
  69.         p= "Save in File Named:";
  70.     else
  71.         p= "Import File Named:";
  72.     }
  73.     
  74.     title->SetString(p);
  75.     
  76.     // remember initial working directory
  77.     strreplace(&initDir, gSystem->WorkingDirectory());
  78.  
  79.     return Dialog::ShowOnWindow(fp);
  80. }
  81.  
  82. void FileDialog::UpdateList()
  83. {
  84.     SafeDelete(current);
  85.     current= new FileData(".");
  86.     SeqCollection *contents;
  87.     contents= current->GetContents();
  88.     Iter next(contents);
  89.     register Data *d;
  90.     VObject *vop;
  91.     
  92.     OrdCollection *files= new OrdCollection;
  93.     while (d= (Data*) next())
  94.     if (vop= MakeFileItem(d))
  95.         files->Add(vop);
  96.     files->Sort();
  97.     collview->SetCollection(files);
  98.  
  99.     if (eti)
  100.     eti->SetString("");
  101. }
  102.  
  103. VObject *FileDialog::MakeFileItem(Data *data)
  104. {
  105.     return new FileItem(data);
  106. }
  107.  
  108. int FileDialog::ItemHeight()
  109. {
  110.     VObject *vop= new FileItem(".", FALSE);
  111.     int h= vop->GetMinSize().extent.y;
  112.     delete vop;
  113.     return h;
  114. }
  115.  
  116. VObject *FileDialog::DoMakeContent()
  117. {
  118.     pathPopup= new PopupButton(cIdPath, cIdNone,
  119.         new Menu("Current Directory", FALSE, FALSE));
  120.     
  121.     collview= new CollectionView(this, new OrdCollection, eCVDontStuckToBorder);
  122.     collview->SetMinExtent(Point(cItemMinWidth, 0));
  123.     collview->SetId(cIdList);
  124.  
  125.     return
  126.     new Matte(
  127.         new VExpander(20,
  128.         new Form(cIdNone, (VObjAlign)(eVObjVBase+eVObjHExpand), gPoint10,
  129.             "Current Directory:", pathPopup,
  130.             0
  131.         ), 
  132.         scroller= new Scroller(collview, 
  133.             Point(cItemMinWidth, ItemHeight()*cNumItems), cIdList),
  134.         new VExpander(gPoint2,
  135.             title,
  136.             eti= new TextField(cIdName, 20),
  137.             0
  138.         ),
  139.         new HBox(20, (VObjAlign)(eVObjVBase|eVObjHEqual|eVObjHExpand),
  140.             openButton= new ActionButton(cIdOk, flags == eFDWrite ? "Save" : "Open", TRUE),
  141.             new ActionButton(cIdCancel, "Cancel"),
  142.             new ActionButton(cIdUpdate, "Update"),
  143.             new ActionButton(cHELP, "Help"),
  144.             0
  145.         ),
  146.         0
  147.         )
  148.     );
  149. }
  150.  
  151. void FileDialog::DoSetDefaults()
  152. {
  153.     UpdatePath();
  154.     UpdateList();
  155. }
  156.  
  157. void FileDialog::DoSetup()
  158. {
  159.     if (flags == eFDWrite) {
  160.     char buf[1000];
  161.     eti->GetString(buf, 1000);
  162.     FileData *fd= new FileData(buf, FALSE, FALSE); 
  163.     openButton->SetLabel(fd->IsDirectory() ? "Open" : "Save", TRUE);
  164.     delete fd;
  165.     }
  166.     openButton->Enable(eti->GetTextSize() > 0);
  167. }
  168.  
  169. void FileDialog::DoRestore() 
  170. {
  171.     gSystem->ChangeDirectory(initDir); 
  172. }
  173.  
  174. void FileDialog::Control(int id, int p, void *v)
  175. {
  176.     VObject *gop;
  177.     
  178.     switch (id) {
  179.     
  180.     case cIdUpdate:
  181.     UpdateList();
  182.     return;
  183.     
  184.     case cIdList:
  185.     switch (p) {
  186.     case cPartCollSelect:
  187.         gop= (VObject*) collview->GetCollection()->At( (int) v );
  188.         char *fname= gop->AsString();
  189.         if (fname && strlen(fname) > 0)
  190.         eti->SetString(gop->AsString());
  191.         break;
  192.     case cPartCollDoubleSelect:
  193.         if (OpenOrChangeDir()) {
  194.         Dialog::Control(cIdOk, cPartAction, v);
  195.         return;
  196.         }
  197.         break;
  198.     }
  199.     return;
  200.     
  201.     case cIdOk:
  202.     if (!OpenOrChangeDir())
  203.         return;
  204.     break;
  205.     
  206.     case cIdPath:
  207.     Data *d= (Data*) pathList->At((int)v-cIdComponent);
  208.     if (d)
  209.         eti->SetString(d->FullName());
  210.     OpenOrChangeDir();
  211.     return;
  212.     }
  213.     Dialog::Control(id, p, v);
  214. }
  215.  
  216. void FileDialog::InputKbd(Token &t)
  217. {
  218.     if (t.IsAscii() && scroller->ContainsPoint(t.Pos)) {
  219.     if (t.Code != '\r' && t.Code != '\n') 
  220.         scroller->Input(t.Pos, t, GetWindow());
  221.     } else
  222.     Manager::InputKbd(t);
  223. }
  224.  
  225. bool FileDialog::ChangeDirectory()
  226. {
  227.     if (fileData->IsDirectory()) {
  228.     if (!gSystem->ChangeDirectory(fileData->FullName()))
  229.         ShowAlert(eAlertNote, "Cannot change directory to @B%s@P", fileData->FullName());
  230.     else {
  231.         UpdatePath();
  232.         UpdateList();
  233.     } 
  234.     return TRUE;
  235.     }
  236.     return FALSE;
  237. }
  238.  
  239. bool FileDialog::OpenOrChangeDir()
  240. {
  241.     char pathname[cPathBuf];
  242.     eti->GetString(pathname, cPathBuf);
  243.     
  244.     if (gSystem->ExpandPathName(pathname, cPathBuf-1)) {
  245.     ShowAlert(eAlertNote, "%s (%s)", gSystem->GetErrorStr(), pathname);
  246.     return FALSE;
  247.     }
  248.     
  249.     SafeDelete(fileData);
  250.     fileData= new FileData(pathname, FALSE, TRUE); // deep
  251.     
  252.     if (ChangeDirectory())
  253.     return FALSE;
  254.     
  255.     char *fname= fileData->FullName();
  256.  
  257.     if (flags == eFDWrite) {
  258.     if (!gSystem->AccessPathName(fname, 0)) {
  259.         if (ShowAlert(eAlertCaution, "File @B%s@P exists! Overwrite ?", fname) != cIdYes)
  260.         return FALSE;
  261.     }
  262.     if (!fileData->IsWritable()) {
  263.         ShowAlert(eAlertNote, "Document @B%s@P is not writable\n%s", fname,
  264.                                 gSystem->GetErrorStr());
  265.         return FALSE;
  266.     }
  267.     } else {
  268.     if (!fileData->IsReadable()) {
  269.         ShowAlert(eAlertNote, "Can't open document @B%s@P for reading\n%s",
  270.                         fname, gSystem->GetErrorStr());
  271.         return FALSE;
  272.     }
  273.     if (WrongType()) {
  274.         ShowAlert(eAlertNote, "File @B%s@P has wrong type (%s)", fname,
  275.                         fileData->Type().AsString());
  276.         return FALSE;
  277.     }
  278.     }
  279.     return TRUE;
  280. }
  281.  
  282. bool FileDialog::WrongType()
  283. {
  284.     if (doc) {
  285.     if (doc->IsKindOf(Document)) {
  286.         if (flags == eFDImport)
  287.         filterfunc= (FilterFunc) &Document::CanLoad;
  288.         else
  289.         filterfunc= (FilterFunc) &Document::CanLoad;
  290.     } else if (doc->IsKindOf(View)) {
  291.         View *v= (View*) doc;
  292.         return ! v->CanPaste(fileData);
  293.     } else
  294.         filterfunc= (FilterFunc) &Application::CanOpen;
  295.     return ! (doc->*filterfunc)(fileData);
  296.     }
  297.     return FALSE;
  298. }
  299.  
  300. void FileDialog::UpdatePath()
  301. {
  302.     Data *here;
  303.     if (pathList) {
  304.     pathList->FreeAll();
  305.     SafeDelete(pathList);
  306.     }
  307.     pathList= new OrdCollection;
  308.     for (here= new FileData("."); here; here= here->GetParent())
  309.     pathList->AddFirst(here);
  310.     
  311.     Iter next(pathList);
  312.     Data *dp;
  313.     SeqCollection *newpath= new OrdCollection;
  314.     for (int i= 0; dp= (Data*)next(); i++)
  315.     newpath->Add(new MenuButtonItem(cIdComponent+i, dp->ShortName()));
  316.     
  317.     pathPopup->SetCollection(newpath);
  318.     pathPopup->SetValue(cIdComponent+i-1);
  319. }
  320.  
  321. //---- FileItem ----------------------------------------------------------------
  322.  
  323. NewMetaImpl0(FileItem, VObject);
  324.  
  325. FileItem::FileItem(char *name, bool shallow) : VObject()
  326. {
  327.     data= new FileData(name, FALSE, !shallow); // shallow
  328. }
  329.  
  330. FileItem::FileItem(Data *d) : VObject()
  331. {
  332.     data= d;
  333. }
  334.  
  335. FileItem::~FileItem()
  336.     SafeDelete(data);
  337. }
  338.  
  339. Metric FileItem::GetMinSize()
  340. {
  341.     byte *n= (byte*) data->ShortName();
  342.     return Metric(gSysFont->Width(n)+20, gSysFont->Spacing()+4, gSysFont->Ascender()+2);
  343. }
  344.  
  345. char *FileItem::AsString()
  346.     return data->ShortName();
  347. }
  348.  
  349. void FileItem::Draw(Rectangle)
  350. {
  351.     byte *n= (byte*) data->ShortName();
  352.  
  353.     Point p= contentRect.origin;
  354.     p.x+= 22;
  355.     p.y+= gSysFont->Ascender()+3;
  356.     GrShowString(gSysFont, Enabled() ? ePatBlack : ePatGrey50, p, n);
  357.  
  358.     Bitmap *bm= data->GetBitmap();
  359.     if (bm) {
  360.     Rectangle br(contentRect.origin, bm->Size());
  361.     br.origin.x+= 2;
  362.     br.origin.y+= 3;
  363.     GrPaintBitMap(br, bm, Enabled() ? ePatBlack : ePatGrey50);
  364.     }
  365. }
  366.  
  367. int FileItem::Compare(Object *op)
  368. {
  369.     FileItem *other= Guard(op,FileItem);
  370.     /*
  371.     bool isdir= data->IsDirectory();
  372.     if (isdir == other->GetData()->IsDirectory())
  373.     return StrCmp((byte*)data->ShortName(), (byte*)other->data->ShortName(), -1, sortmap);
  374.     if (isdir)
  375.     return -1;
  376.     return 1;
  377.     */
  378.     return StrCmp((byte*)data->ShortName(), (byte*)other->data->ShortName(),
  379.                                     -1, sortmap);
  380. }
  381.  
  382.